// For debug output to console
Canvas.debug = true;

function Canvas() {

	this.dprint("CanvasV2 Constructor");
	
	this.isMakingShape = false;
	this.objects = new Array();

	this.initDomElem();

	// Set up default attributes
	for( var i=0; i<Canvas.attributes.length; i++ ) {
		var attr = Canvas.attributes[i];
		//this.dprint("attr: " + attr.name + " value: " + attr.value);
		this.setAttribute(attr.name, attr.value);
	}

	this.selectedObject = null;	
	
	$(document).keydown(function(e) {
		//cprint(e.keyCode);
		if (e.keyCode == 61) { // Create new object
			theCanvas().beginCreatingShape();
		} else if (e.keyCode == 49) {
			theCanvas().beginCreatingShape("input type='text'");
		} else if (e.keyCode == 46) { // Delete object
		
			theCanvas().removeObject(theCanvas().getSelectedObject());
			//CanvasObject.selectedObject().destroy();
		
		} else { //if (e.keyCode == {
			//cprint("key: " + e.keyCode);
		}
	});
}

Canvas.className = "Canvas";

// Singleton instance
Canvas._theCanvas = null;
function theCanvas() { return Canvas._theCanvas; }
//Canvas.theCanvas = function() { return _theCanvas; };

// Attributes that can be get/set via setAttribute method
// Each attribute is associated with a corresponding getter/setter of
// the following name format:
//   Attribute:	attributeX
//   Getter:	this.attributeX  (accesses variable directly)
//   Setter:	setAttributeX(value);
Canvas.attributes = new Array(
	{name: "id", value: "canvas"},
	{name: "width", cssName: "width", value: 500},
	{name: "height", cssName: "height", value: 500},
	{name: "background", cssName: "background", value: "transparent"},
	{name: "backgroundImage", cssName: "background-image", value: ""}
);

Canvas.prototype.initDomElem = function() {
	this.domElem = $('<div id="canvas" class="canvas"></div>');
	$("#canvas_container").append(this.domElem);

	var obj = this;

	this.domElem.click(function(e) {
	
		obj.dprint("click");
		obj.setSelectedObject(null);
		
		if(obj.isMakingShape && obj.shapeBeingMade==undefined) {
			obj.dprint("First shape corner");
		
			obj.shapeBeingMade = new CanvasObject(obj.isMakingType);
			obj.addObject(obj.shapeBeingMade);
			obj.setSelectedObject(obj.shapeBeingMade);
			
			obj.anchorPoint = { x: (e.pageX - obj.domElem.offset().left),
								 y: (e.pageY - obj.domElem.offset().top) };
			
			obj.dprint("" + obj.anchorPoint.x + " " + obj.anchorPoint.y);
			
			obj.shapeBeingMade.setX( obj.anchorPoint.x );
			obj.shapeBeingMade.setY( obj.anchorPoint.y );
			obj.shapeBeingMade.setWidth(10);
			obj.shapeBeingMade.setHeight(10);
		} else if (obj.isMakingShape) {
			obj.dprint("Second shape corner");
			
			obj.endCreatingShape();
		} else {

		}
	});
	
	this.domElem.mousemove(function(e) {
		
		if (obj.isMakingShape && obj.shapeBeingMade != undefined) {
			
			var p = { x: (e.pageX - obj.domElem.offset().left),
					  y: (e.pageY - obj.domElem.offset().top) };
		
			if (p.x > obj.anchorPoint.x) {
				obj.shapeBeingMade.setWidth( p.x - obj.anchorPoint.x );
			} else {
				obj.shapeBeingMade.setX( p.x );
				obj.shapeBeingMade.setWidth( obj.anchorPoint.x - p.x );
			}
			
			if (p.y > obj.anchorPoint.y) {
				obj.shapeBeingMade.setHeight( p.y - obj.anchorPoint.y );
			} else {
				obj.shapeBeingMade.setY( p.y );
				obj.shapeBeingMade.setHeight( obj.anchorPoint.y - p.y );
			}
		
			obj.dprint("" + p.x + " " + p.y);
		}
	});
}

Canvas.prototype.dumpHtml = function() {
	this.dprint("dumpHtml");
	
	// pre tag keeps string properly formatted
	//return "<pre>" + escapeHtml(this.dumpCss()) + escapeHtml(this.dumpRawHtml()) + "</pre>";
};

Canvas.prototype.dumpRawHtml = function() {

	var str = "";
	//str += this.dumpCss();		
	str += '<div id="'+this.id+'" class="canvas">\n';
	for (var i in this.objects) {
		str += "\t" + this.objects[i].dumpHtml() + "\n";
	}
	str += '</div>';
	
	return str;
}

Canvas.prototype.dumpCss = function() {
	var str = "";
	
	str += "<style>\n";
	
	str += "\t#" + this.id + " {\n";
	
	str += "\t\t position: absolute;\n";
	for (var i=0; i<Canvas.attributes.length; i++) {
		var attr = Canvas.attributes[i];
		
		if (attr.cssName != undefined) {
			str += "\t\t" + attr.cssName + ":" + this[attr.name] + "; \n";
		}
	}
	str += "\t}\n\n";
	
	for (var i in this.objects) {
		str += this.objects[i].dumpCss() + "\n";
	}
	str += "</style>\n";
	
	return str;
}

Canvas.prototype.beginCreatingShape = function(type) {
	this.dprint("beginCreatingShape: " + type);
	this.domElem.toggleClass("creating", true);
	this.isMakingShape = true;
	
	if (type == undefined) {
		this.isMakingType = "div";
	} else  {
		this.isMakingType = type;
	}
};

Canvas.prototype.endCreatingShape = function() {
	this.dprint("endCreatingShape");

	this.isMakingShape = false;
	this.domElem.toggleClass("creating", false);
	//this.addObject(this.shapeBeingMade);
	this.shapeBeingMade = undefined;
	this.isMakingType = undefined;
	this.anchorPoint = undefined;
};

Canvas.prototype.setAttribute = function(name, value) {
	this.dprint("setAttribute: " + name + "->" + value);

	var methodName = "set" + name.substring(0,1).toUpperCase() + name.substring(1);
	this[methodName](value);
};

Canvas.prototype.getAttribute = function(name) {
	this.dprint("getAttribute: " + name);
	return this[name];	
};

Canvas.prototype.addObject = function(o) {
	this.dprint("addObject: " + o.id);
	
	this.objects[o.id] = o;
	o.parent = this;
	this.domElem.append(o.domElem);
};

// Is o a domElem? or an object?
Canvas.prototype.removeObject = function(o) {
	this.dprint("removeObject: " + o.id);
	
	o.parent = undefined;
	delete this.objects[o.id]; // remove from array of objects
	//o.remove();
	
	o.destroy();
};

Canvas.prototype.getSelectedObject = function() {
	return this.selectedObject;
};

Canvas.prototype.setSelectedObject = function(o) {
	
	this.dprint("setSelectedObject: " + o);
	
	if (this.selectedObject != null) {
		this.dprint("selectedObject was null before");	
		this.selectedObject.setIsSelected(false);
		this.selectedObject = null;
	}
	
	if (o == null) {
		this.dprint("set selected to null");
	} else {
	
		var obj = this.objects[o.id];
		if (obj == this.selectedObject) {
			//this.dprint("object already selected");
			//return;
		}
		
		//this.dprint("setSelectedObject: " + obj);
		this.selectedObject = obj;
		obj.setIsSelected(true);
	
	}
	
	this.selectedChanged();
};

Canvas.prototype.selectedChanged = function() {
	theControlPanel().fullRefresh();
}

Canvas.prototype.valueChanged = function() {
	this.dprint("valueChanged");
	
	// Handles case where is called from constructor
	if (theCanvas() != null) {
		theControlPanel().fullRefresh();
		//updateControlPanel();
	}
};

//
//	Canvas Attribute Getters/Setters
//

Canvas.prototype.setId = function(name) {
	this.dprint("setId: " + name);
	
	this.id = name;
	this.domElem.attr("id", name);
	this.valueChanged();
}

Canvas.prototype.setWidth = function(w) {
	this.dprint("setWidth");
	
	this.width = w;
	this.domElem.css("width", ""+(w)+"px");
	this.valueChanged();
};

Canvas.prototype.setHeight = function(h) {
	this.dprint("setHeight");
	
	this.height = h;
	this.domElem.css("height", ""+(h)+"px");
	this.valueChanged();
};

Canvas.prototype.setBackground = function(bg) {
	this.dprint("setBackground");
	this.domElem.css("background", bg);
}

Canvas.prototype.setBackgroundImage = function(imgUrl) {
	this.dprint("setBackgroundImage");
	
	if (imgUrl == "") {
		this.backgroundImage = "";
		this.domElem.css("background-image", "none");	
	} else {
		//this.domElem.css("background-image", "url('"+imgUrl+"')");
		this.backgroundImage = "url('"+imgUrl+"')";
		this.domElem.css("background-image", this.backgroundImage);
		
		var _parent = this;
		var _img = new Image();
		_img.src=imgUrl;
		
		_img.onload = function() {
			cprint("image loaded");
			cprint("w: "+_img.width);
			cprint("h: "+_img.height);
			
			_parent.setWidth(_img.width);
			_parent.setHeight(_img.height);
		}
		_img.onerror=function() {
			cprint("image error");
		};
		_img.onabort=function() {
			cprint("image abort");
		};
	}
	
	this.valueChanged();
};

// Debug output to console
Canvas.prototype.dprint = function(str) {
	if (Canvas.debug) {
		cprint(Canvas.className + ": " + str, "#00ff00");
	}
};

